﻿package velbus.modules.part 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	import flash.xml.XMLNode;
	import mx.containers.Canvas;
	import mx.controls.Button;
	import mx.controls.Label;
	import mx.core.Application;
	import mx.core.UIComponent;
	import SWFKit.Dialogs;
	import SWFKit.Shell;
	import velbus.modules.data.Playlist;
	import velbus.modules.PlaylistModule;
	import velbus.modules.PushButtonAndTimer;
	import velbus.modules.VelbusModule;
	import velbus.Packet;
	import velbus.Velbus;
	import velbus.VelbusEvent;
	
	/**
	* ...
	* @author Gert Stalpaert (gert@stogo.net)
	*/
	public class Switch extends Canvas
	{
		
		///used to send a button 'push' command
		public static const COMMAND_PUSH_BUTTON_STATUS:int = 0x00;
		public static const COMMAND_CLEAR_LED:int = 0xF5;
		public static const COMMAND_SET_LED:int = 0xF6;
		public static const COMMAND_SLOW_BLINKING_LED:int = 0xF7;
		public static const COMMAND_FAST_BLINKING_LED:int = 0xF8;
		public static const COMMAND_VERY_FAST_BLINKING_LED:int = 0xF9;
		
		public static const PUSH_MODE_PRESS:int = 1;
		public static const PUSH_MODE_RELEASE:int = 2;
		public static const PUSH_MODE_LONG_PRESS:int = 3;
		
		public static const BIT_LED_CONTINUOUS:int = 2;
		public static const BIT_LED_SLOW_BLINKING:int = 3;
		public static const BIT_LED_FAST_BLINKING:int = 4;
		
		///hex value to send corresponding to a certain btn nr (array index = btn nr)
		static private const BUTTON_NR_HEX:Array = [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80];
		
		protected var _velbus:Velbus;
		protected var _address:int;
		///zero based btn nr
		protected var _buttonNr:int;
		protected var _button:Button;
		protected var _caption:String
		
	
		[Embed(source='assets/leds.swf#ledOn')]
		private var _ledOn:Class;
		
		[Embed(source='assets/leds.swf#ledOff')]
		private var _ledOff:Class;
		
		[Embed(source='assets/leds.swf#ledBlinkSlow')]
		private var _ledBlinkSlow:Class;
		
		[Embed(source='assets/leds.swf#ledBlinkFast')]
		private var _ledBlinkFast:Class;

		[Embed(source='assets/leds.swf#ledBlinkVeryFast')]
		private var _ledBlinkVeryFast:Class;
		
		private var _shortPressCommands:XMLList;
		private var _longPressCommands:XMLList;
		private var _longPressTimer:Timer;
		
		/**
		 * 
		 * @param	velbus
		 * @param	address
		 * @param	buttonNr 0 - 7 (zero-based)
		 * @param	caption_
		 */
		public function Switch(velbus:velbus.Velbus, address:int, buttonNr:int, caption_:String) 
		{
			_velbus = velbus;
			_address = address;
			_buttonNr = buttonNr;
			super();
			percentWidth = 100;
			_button = new Button();
			caption = caption_;
			_button.x = 5;
			_button.percentWidth = 96;
			_button.addEventListener(MouseEvent.MOUSE_DOWN, onButtonPress);
			_button.addEventListener(MouseEvent.MOUSE_UP, onButtonRelease);
			_button.setStyle("textAlign", "left");
			_button.setStyle("paddingLeft", 20);
			_button.setStyle("paddingTop", 11);
			this.addChild(_button);
			_velbus.addEventListener(VelbusEvent.PACKET_RECEIVED, onPacketReceived);
			this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			
			_longPressTimer = new Timer(150);
			_longPressTimer.addEventListener(TimerEvent.TIMER, onLongPressTimer);
			
		}
		
		private function onAddedToStage(e:Event):void 
		{
			//showLink();
			initCommands();
		}
		
		private function initCommands():void
		{
			/*
			<trigger type="Switch">
				<commands address="10" buttonNr="5" press="true" repeatOnLongPress="true">
					<command type="run" showWindowFlag="0"><![CDATA["C:\Program Files\IRTrans\IRClient.exe" localhost gert "vol up"]]></command>
				</commands>
				<commands address="10" buttonNr="7" press="true" repeatOnLongPress="true">
					<command type="run" showWindowFlag="0"><![CDATA["C:\Program Files\IRTrans\IRClient.exe" localhost gert "vol down"]]></command>
				</commands>
				<!--
				<commands address="10" buttonNr="5" press="true" repeatOnLongPress="false" reapeatInterval="50">
					<command type="lcd" lcdLine="3"><![CDATA[^|Dit is een e|+]]></command>
				</commands>
				-->
			</trigger>
			*/
			
			
			//get all commands for this switch that have a press event
			_shortPressCommands = VelbusSocket.xmlData.eventTriggers.trigger.(@type == "Switch").commands.(parseInt(@address, 16) == _address && parseInt(@buttonNr) == _buttonNr && @press == "true").command;
			 
			//get all commands for this switch that have a longPress event
			_longPressCommands = VelbusSocket.xmlData.eventTriggers.trigger.(@type == "Switch").commands.(parseInt(@address, 16) == _address && parseInt(@buttonNr) == _buttonNr && @repeatOnLongPress == "true").command;
		}
		
		private function showLink():void
		{
			var linkCanvas:Sprite = new UIComponent();
			Application.application.moduleCanvas.addChild(linkCanvas);
			var p:Point = VelbusModule(Application.application.modules[0x03]).localToGlobal(new Point());
			p = linkCanvas.globalToLocal(p);
			linkCanvas.graphics.lineStyle(1, 0xFF0000, 1, true);
			linkCanvas.graphics.moveTo(p.x, p.y); trace("p>" + p);
			p = this.localToGlobal(new Point()); trace("sw:" + p);
			p = linkCanvas.globalToLocal(p);
			linkCanvas.graphics.lineTo(p.x, p.y); trace("p<" + p);
			//linkCanvas.graphics.lineTo(800, 200); 
			
		}
		
		private function onLedTimer(e:TimerEvent):void 
		{
			_button.selected = !_button.selected;
		}
		
		private function onPacketReceived(e:VelbusEvent):void 
		{
			//return if event is for other address
			if (e.packet.address != _address) {
				return
			}
			
			var mask:Number;
			var maskedValue:Number;
				
			
			if (e.packet.command == VelbusModule.RECEIVE_MODULE_STATUS) {
				_button.setStyle("icon", _ledOff);
				_button.selected = false;
				mask = BUTTON_NR_HEX[_buttonNr];
				
				maskedValue = e.packet.getDataByte(BIT_LED_SLOW_BLINKING) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledBlinkSlow);
				}
				maskedValue = e.packet.getDataByte(BIT_LED_FAST_BLINKING) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledBlinkFast);
				}
				//trace(e.packet)
				//overrules blinking leds
				maskedValue = e.packet.getDataByte(BIT_LED_CONTINUOUS) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledOn);
				}
			} 
			
			if (e.packet.command == Switch.COMMAND_CLEAR_LED) {
				mask = BUTTON_NR_HEX[_buttonNr];
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledOff);
				}
			}
			
			if (e.packet.command == Switch.COMMAND_SET_LED) {
				mask = BUTTON_NR_HEX[_buttonNr];
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledOn);
					_button.selected = true;
				}
			}
			
			if (e.packet.command == Switch.COMMAND_SLOW_BLINKING_LED) {
				mask = BUTTON_NR_HEX[_buttonNr];
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledBlinkSlow);
				}
			}
			
			if (e.packet.command == Switch.COMMAND_FAST_BLINKING_LED) {
				mask = BUTTON_NR_HEX[_buttonNr];
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledBlinkFast);
				}
			}
			
			if (e.packet.command == Switch.COMMAND_VERY_FAST_BLINKING_LED) {
				mask = BUTTON_NR_HEX[_buttonNr];
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
					_button.setStyle("icon", _ledBlinkVeryFast);
					trace("fast!")
				}
			}
			
			if (e.packet.command == Switch.COMMAND_PUSH_BUTTON_STATUS) {
				
				
				mask = BUTTON_NR_HEX[_buttonNr];
				
				//short press
				maskedValue = e.packet.getDataByte(1) & mask;
				if (maskedValue == mask) {
						
					//hard coded: alles uit knop aan trap:
					if (_address == 0x12 && _buttonNr == 0) {
						var t:Timer = new Timer(500, 1);
						t.addEventListener(TimerEvent.TIMER, onDelayedFastOn);
						t.start();
					}
					
					
					runCommands(_shortPressCommands);
					
					
					/*if (_buttonNr == 4 && (_address == 0x10 || _address == 0x11)) {
						try {
							shell.run('"C:\\Program Files\\IRTrans\\IRClient.exe" localhost gert "input video1"', 0);
							shell.run('"C:\\Program Files\\Windows Media Player\\wmplayer.exe" http://mp3.streampower.be/stubru-high');
							//PushButtonAndTimer.setLcdLine(0x10, 3, "ON < radio > OFF");
							//C:\Program Files\Windows Media Player\plugins\Now Playing\data.xml
						} catch (e:Error) {
						}
					}
					if (_buttonNr == 5 && (_address == 0x10 || _address == 0x11)) {
						try {
							shell.run('"C:\\Program Files\\Windows Media Player\\wmplayer.exe" "D:\\Documents of Gert\\Music\\Playlists\\empty.wpl"');
							shell.run('"C:\\Program Files\\IRTrans\\IRClient.exe" localhost gert "receiver off"', 0);
						} catch (e:Error) {
						}
					}
					if (_buttonNr == 6 && (_address == 0x10 || _address == 0x11)) {
						try {
							shell.run('"C:\\Program Files\\IRTrans\\IRClient.exe" localhost gert "vol down"', 0);
						} catch (e:Error) {
						}
					}
					if (_buttonNr == 7 && (_address == 0x10 || _address == 0x11)) {
						try {
							shell.run('"C:\\Program Files\\IRTrans\\IRClient.exe" localhost gert "vol up"', 0);
						} catch (e:Error) {
						}
					}*/
				}
				
				
				//long press
				maskedValue = e.packet.getDataByte(3) & mask;
				if (maskedValue == mask) {
					runCommands(_longPressCommands, true);
				}
				
				//release
				maskedValue = e.packet.getDataByte(2) & mask;
				if (maskedValue == mask) {
					_longPressTimer.stop();
				}
			}

		}
		
		private function runCommands(commands:XMLList, startLongPressTimer:Boolean = false):void {
		
			var i:int;
			var command:XML;
			for each(command in commands) {
				VelbusSocket.info.text += (command.@type + " - " + command + "\n")
				if (command.@type == "run") {
					try {
						var shell:Shell = new Shell();	
						shell.run(command.toString(), parseInt(command.@showWindowFlag));
					} catch (e:Error) {
						VelbusSocket.info.text += "Warning: executing run commands are not possible if running from web browser" + "\n";
					}
				} else if (command.@type == "lcd") {
					PushButtonAndTimer.setLcdLine(_address, command.@lcdLine, command);
				} else if (command.@type == "playlist") {
					PlaylistModule[command](_address);
				}
				if (startLongPressTimer) {
					_longPressTimer.start();
				}
			}
		}
		
		
		
		
		private function onLongPressTimer(e:TimerEvent):void 
		{
			runCommands(_longPressCommands, false);
		}
		
		private function onDelayedFastOn(e:TimerEvent):void 
		{
			Velbus.addToSendQueue(new Packet(0x02, Packet.PRIORITY_HIGH, 5, VelbusModule.ArrayToByteArray([0x07, 0x01, 0x1C, 0xFF, 0xFF]), false));
			var t:Timer = new Timer(500, 1);
			t.addEventListener(TimerEvent.TIMER, onDelayedSlowFadeOut);
			t.start();
		}
		
		private function onDelayedSlowFadeOut(e:TimerEvent):void 
		{
			Velbus.addToSendQueue(new Packet(0x02, Packet.PRIORITY_HIGH, 5, VelbusModule.ArrayToByteArray([0x07, 0x01, 0x00, 0x00, 0xF4]), false));			
		}

		
		public function set caption(value:String): void 
		{
			_caption = value;
			_button.label = _caption;
		}
		
		private function onButtonPress(e:MouseEvent):void 
		{
			push(Switch.PUSH_MODE_PRESS);
		}

		private function onButtonRelease(e:MouseEvent):void 
		{
			push(Switch.PUSH_MODE_RELEASE);
		}
		
		/**
		 * send a push command
		 * @param	pushMode	default = PUSH_MODE_PRESS; can also be PUSH_MODE_RELEASE and PUSH_MODE_LONG_PRESS (>0.85s)
		 */
		public function push(pushMode:int = PUSH_MODE_PRESS):Packet {
			var ba:ByteArray = new ByteArray();
			ba[0] = COMMAND_PUSH_BUTTON_STATUS;
			ba[1] = 0x00;
			ba[2] = 0x00;
			ba[3] = 0x00;
			ba[pushMode] = BUTTON_NR_HEX[_buttonNr]
			var p:Packet = new Packet(_address, Packet.PRIORITY_HIGH, 4, ba, false);
			Velbus.addToSendQueue(p);
			return p;
		}
		
	}
	
}